package com.hospital.hl7package.function;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.DataTypeException;
import ca.uhn.hl7v2.model.ExtraComponents;
import ca.uhn.hl7v2.model.Structure;
import ca.uhn.hl7v2.model.v24.message.ACK;
import ca.uhn.hl7v2.model.v24.message.SIU_S12;
import ca.uhn.hl7v2.model.v24.segment.*;
import com.hospital.hl7package.module.entity.OperationMaster;
import com.hospital.hl7package.module.entity.OperationName;
import com.hospital.hl7package.module.entity.OperationSchedule;
import com.hospital.hl7package.module.entity.ScheduledOperationName;
import com.hospital.hl7package.module.service.OperationMasterService;
import com.hospital.hl7package.module.service.OperationScheduleService;
import com.hospital.hl7package.module.service.ScheduledOperationNameService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author lvyao
 * @description 手麻信息
 * @date 2020/9/12
 */
@Service
@Slf4j
public class Hl7HelpperFunc {
    @Resource
    private ScheduledOperationNameService scheduledOperationNameService;

    @Resource
    private OperationScheduleService operationScheduleService;

    @Resource
    private OperationMasterService operationMasterService;

    public Map<String, Object> setOperationInfo(SIU_S12 siu_s12) throws ParseException, HL7Exception {
        Map<String, Object> map = new HashMap<>();
        OperationMaster operationMaster = new OperationMaster();
        MSH msh = siu_s12.getMSH();
        String sendCode = msh.getSendingApplication().getHd1_NamespaceID().getValue();
        String sendName = msh.getSendingFacility().getHd1_NamespaceID().getValue();
        String receiveCode = msh.getReceivingApplication().getHd1_NamespaceID().getValue();
        String reveiveName = msh.getReceivingFacility().getHd1_NamespaceID().getValue();
        String messageTime = String.valueOf(msh.getMsh7_DateTimeOfMessage().getTs1_TimeOfAnEvent());
        String messageType = msh.getMessageType().getMessageType().getValue();
        String messageEvent = msh.getMsh9_MessageType().getTriggerEvent().getValue();
        String guid = msh.getMessageControlID().getValue();
        String hos_name = msh.getPrincipalLanguageOfMessage().getCe1_Identifier().getValue();
        SCH sch = siu_s12.getSCH();
        String operSchedule = sch.getSch1_PlacerAppointmentID().getEi1_EntityIdentifier().getValue();
        OperationSchedule operationSchedule = operationScheduleService.getOperationSchedule(operSchedule);
        map.put("OperationMaster", operationMaster);
        //若未找到手术申请信息则直接找到最大operId
//        if (operationSchedule == null) {
//            return map;
//        }
        String reqDate = sch.getAppointmentTimingQuantity(0).getTq4_StartDateTime().getTs1_TimeOfAnEvent().getValue();
        String scheduleDate = sch.getAppointmentTimingQuantity(0).getEndDateTime().getTs1_TimeOfAnEvent().getValue();

        List<ScheduledOperationName> scheduledOperationNameList = scheduledOperationNameService.getScheduledOperationName(operSchedule);
        List<OperationName> operationNameList = new ArrayList<>();
        for (ScheduledOperationName scheduledOperationName : scheduledOperationNameList) {
            OperationName operationName = new OperationName();
            operationName.setPatientId(scheduledOperationName.getPatientId());
            operationName.setVisitId(scheduledOperationName.getVisitId());
            operationName.setOperId(scheduledOperationName.getScheduleId());
            operationName.setOperationNo(scheduledOperationName.getOperationNo());
            operationName.setOperation(scheduledOperationName.getOperation());
            operationName.setOperationScale(scheduledOperationName.getOperationScale());
            operationName.setWoundGrade(scheduledOperationName.getWoundGrade());
            operationNameList.add(operationName);
        }
        map.put("OperationName", operationNameList);

        DG1 dg11 = siu_s12.getPATIENT(0).getDG1(0);
        PID pid = siu_s12.getPATIENT(0).getPID();
        PV1 pv1 = siu_s12.getPATIENT(0).getPV1();
        AIL ail = (AIL) siu_s12.get("AIL");
        String notice = siu_s12.getNTE(0).getComment(0).getValue();
        String oper1 = dg11.getDiagnosisPriority().getValue();
        String mailingAddress = pid.getPatientAddress(0).getStreetAddress().getStreetOrMailingAddress().getValue();
        String patId = pid.getPatientIdentifierList(0).getID().getValue();
        operationMaster.setPatientId(patId);
        String visitId = pv1.getSetIDPV1().getValue();
        operationMaster.setVisitId(Integer.parseInt(visitId));

        OperationMaster operation = operationMasterService.getOperation(operSchedule);
        int operId = 0;
        if (operation == null) {
            operId = operationSchedule == null ? operationMasterService.getMaxOperId(patId, visitId) : operationSchedule.getScheduleId();
        } else {
            operId = operation.getOperId();
        }
        operationMaster.setOperId(operId);
        String value = pv1.getAssignedPatientLocation().getFacility().getNamespaceID().getValue();
        String deptStayed1 = operationSchedule == null ? "" : operationSchedule.getDeptStayed();
        String deptStayed = null;
        if (deptStayed1 == null) {
            deptStayed = value;
        } else {
            deptStayed = getrealVal(value, deptStayed1);
        }
        operationMaster.setDeptStayed(deptStayed);
        String room = operationSchedule == null ? "" : operationSchedule.getOperatingRoom();
        operationMaster.setOperatingRoom(getrealVal(ail.getLocationResourceID().getPointOfCare().getValue(), room));
        String roomNo = operationSchedule == null ? "" : operationSchedule.getOperatingRoomNo();
        operationMaster.setOperatingRoomNo(getrealVal(ail.getLocationResourceID().getRoom().getValue(), roomNo));
        String diagBeforeOperation;
        String diagAfterOperation = null;
        String diagBeforeOperation1 = null;
        String beforeOperation = null;
        if (oper1 != null && oper1.equals("1")) {
            diagBeforeOperation1 = operationSchedule == null ? "" : operationSchedule.getDiagBeforeOperation();
            diagBeforeOperation = getrealVal(dg11.getDiagnosisDescription().getValue(), diagBeforeOperation1);
            diagAfterOperation = siu_s12.getPATIENT(0).getDG1(1).getDiagnosisDescription().getValue();
        } else {
            beforeOperation = operationSchedule == null ? "" : operationSchedule.getDiagBeforeOperation();
            diagBeforeOperation = getrealVal(siu_s12.getPATIENT(0).getDG1(1).getDiagnosisDescription().getValue(), beforeOperation);
            diagAfterOperation = dg11.getDiagnosisDescription().getValue();
        }
        operationMaster.setDiagBeforeOperation(diagBeforeOperation == null?"":diagAfterOperation);
        operationMaster.setDiagAfterOperation(diagAfterOperation);

        Structure[] aips = siu_s12.getAll("AIP");
        AIS ais = (AIS) siu_s12.get("AIS");
        List<AIP> aipList = new ArrayList<>();
        for (Structure structure : aips) {
            aipList.add((AIP) structure);
        }
        String emergencyIndicator = ais.getAis10_FillerStatusCode().getCe1_Identifier().getValue();
        operationMaster.setEmergencyIndicator(stringToInteger(emergencyIndicator));
        String operationScale = operationSchedule == null ? "" : operationSchedule.getOperationScale();
        operationMaster.setOperationScale(getrealVal(ais.getAis11_PlacerSupplementalServiceInformation(0).getCe1_Identifier().getValue(), operationScale));
        String isolationIndicator = operationSchedule == null ? "0" : ais.getPlacerSupplementalServiceInformation(0).getCe4_AlternateIdentifier().getValue();
        operationMaster.setIsolationIndicator(stringToInteger(isolationIndicator));
        operationMaster.setOperationClass(ais.getAis10_FillerStatusCode().getCe3_NameOfCodingSystem().getValue());
        String operationDept = operationSchedule == null ? "" : operationSchedule.getOperatingDept();
        operationMaster.setOperatingDept(getrealVal(ail.getLocationResourceID().getBed().getValue(), operationDept));
        String surgeon = operationSchedule == null ? "" : operationSchedule.getSurgeon();
        operationMaster.setSurgeon(getrealVal(aipList.get(0).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), surgeon));
        String firstAssistant = operationSchedule == null ? "" : operationSchedule.getFirstAssistant();
        operationMaster.setFirstAssistant(getrealVal(aipList.get(3).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), firstAssistant));
        String secondAssistant = operationSchedule == null ? "" : operationSchedule.getSecondAssistant();
        operationMaster.setSecondAssistant(getrealVal(aipList.get(4).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), secondAssistant));
        String thirdAssistant = operationSchedule == null ? "" : operationSchedule.getThirdAssistant();
        operationMaster.setThirdAssistant(getrealVal(aipList.get(5).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), thirdAssistant));
        String fourthAssistant = operationSchedule == null ? "" : operationSchedule.getFourthAssistant();
        operationMaster.setFourthAssistant(getrealVal(aipList.get(6).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), fourthAssistant));

        operationMaster.setAnesthesiaMethod(ais.getAis11_PlacerSupplementalServiceInformation(0).getCe3_NameOfCodingSystem().getValue());
        String anesthesiaDoctor = operationSchedule == null ? "" : operationSchedule.getAnesthesiaDoctor();
        operationMaster.setAnesthesiaDoctor(getrealVal(aipList.get(11).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), anesthesiaDoctor));
        String anesthesiaAssistant = operationSchedule == null ? "" : operationSchedule.getAnesthesiaAssistant();
        operationMaster.setAnesthesiaAssistant(getrealVal(aipList.get(12).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), anesthesiaAssistant));
        String bloodTranDoctor = operationSchedule == null ? "" : operationSchedule.getBloodTranDoctor();
        operationMaster.setBloodTranDoctor(getrealVal(aipList.get(2).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), bloodTranDoctor));
        String firstOperationNurse = operationSchedule == null ? "" : operationSchedule.getFirstOperationNurse();
        operationMaster.setFirstOperationNurse(getrealVal(aipList.get(7).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), firstOperationNurse));
        String secondOperationNurse = operationSchedule == null ? "" : operationSchedule.getSecondOperationNurse();
        operationMaster.setSecondOperationNurse(getrealVal(aipList.get(8).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), secondOperationNurse));
        String firstSupplyNurse = operationSchedule == null ? "" : operationSchedule.getFirstSupplyNurse();
        operationMaster.setFirstSupplyNurse(getrealVal(aipList.get(9).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), firstSupplyNurse));
        String secondSupplyNurse = operationSchedule == null ? "" : operationSchedule.getSecondSupplyNurse();
        operationMaster.setSecondSupplyNurse(getrealVal(aipList.get(10).getAip3_PersonnelResourceID(0).getXcn2_FamilyName().getFn1_Surname().getValue(), secondSupplyNurse));
        String nurseShiftIndicator = ais.getAis10_FillerStatusCode().getCe6_NameOfAlternateCodingSystem().getValue();

        operationMaster.setNurseShiftIndicator(stringToInteger(nurseShiftIndicator));
        String startDateTime = ais.getAis3_UniversalServiceIdentifier().getCe1_Identifier().getValue();
        if (startDateTime != null) {
            operationMaster.setStartDateTime(new SimpleDateFormat("yyyyMMddHHmmss").parse(startDateTime));
        }
        String endDateTime = ais.getAis3_UniversalServiceIdentifier().getCe2_Text().getValue();
        if (endDateTime != null) {
            operationMaster.setEndDateTime(new SimpleDateFormat("yyyyMMddHHmmss").parse(endDateTime));
        }

        String satisfactionDegree = ais.getAis3_UniversalServiceIdentifier().getCe3_NameOfCodingSystem().getValue();
        operationMaster.setSatisfactionDegree(stringToInteger(satisfactionDegree));
        String smoothIndicator = ais.getAis6_StartDateTimeOffsetUnits().getCe3_NameOfCodingSystem().getValue();
        operationMaster.setSmoothIndicator(stringToInteger(smoothIndicator));
        String inFluidsAmount = ais.getAis12_FillerSupplementalServiceInformation(0).getCe1_Identifier().getValue();
        operationMaster.setInFluidsAmount(stringToInteger(inFluidsAmount));
        String outpFluidsAmount = ais.getAis12_FillerSupplementalServiceInformation(0).getCe2_Text().getValue();
//        operationMaster.setOutFluidsAmount(stringToInteger(outpFluidsAmount));
        String bloodLossed = ais.getAis12_FillerSupplementalServiceInformation(0).getCe3_NameOfCodingSystem().getValue();
        operationMaster.setBloodLossed(stringToInteger(bloodLossed));
        String bloodTransfered = ais.getAis12_FillerSupplementalServiceInformation(0).getCe4_AlternateIdentifier().getValue();
        operationMaster.setBloodTransfered(stringToInteger(bloodTransfered));
        String enterBy = operationSchedule == null ? "" : operationSchedule.getEnteredBy();
        operationMaster.setEnteredBy(getrealVal(sch.getEnteredByPerson(0).getIDNumber().getValue(), enterBy));
        String returnDateTime = ais.getAis3_UniversalServiceIdentifier().getCe5_AlternateText().getValue();
        String url = ais.getAis10_FillerStatusCode().getCe5_AlternateText().getValue();
        ExtraComponents extraComponents = ais.getAis10_FillerStatusCode().getCe5_AlternateText().getExtraComponents();
        String encode = extraComponents.getComponent(0).getData().encode();
        String encode1 = extraComponents.getComponent(1).getData().encode();
        String encode2 = extraComponents.getComponent(2).getData().encode();
        url = url + "&" + encode + "&" + encode1 + "&" + encode2;
        operationMaster.setDocumentUrl(url);
        String operLevel = ais.getAis3_UniversalServiceIdentifier().getCe6_NameOfAlternateCodingSystem().getValue();
        if (returnDateTime != null) {
            operationMaster.setReturnDateTime(new SimpleDateFormat("yyyyMMddHHmmss").parse(returnDateTime));
        }
        String arriveDatetime = ais.getUniversalServiceIdentifier().getAlternateIdentifier().getValue();
        if (arriveDatetime != null) {
            operationMaster.setArriveDateTime(new SimpleDateFormat("yyyyMMddHHmmss").parse(arriveDatetime));
        }
        String enterDate = msh.getDateTimeOfMessage().getTimeOfAnEvent().getValue();
        if (enterDate != null) {
            operationMaster.setEnterDate(new SimpleDateFormat("yyyyMMddHHmmss").parse(enterDate));
        }
        map.put("OperationMaster", operationMaster);
        return map;
    }

    public String getAck(String hospitalName,String guid, String sendSystemName, String sendSystemCode, String receiveSystemName, String receiveSystemCode, String messageStatus, String messageType, String triggerEvent, String versionId) throws DataTypeException {
        ACK ack = new ACK();
        ack.getMSH().getMsh1_FieldSeparator().setValue("|");
        ack.getMSH().getMsh2_EncodingCharacters().setValue("^~\\&");
        ack.getMSH().getMsh3_SendingApplication().getHd1_NamespaceID().setValue(sendSystemName);
        ack.getMSH().getMsh4_SendingFacility().getHd1_NamespaceID().setValue(sendSystemCode);
        ack.getMSH().getMsh5_ReceivingApplication().getHd1_NamespaceID().setValue(receiveSystemName);
        ack.getMSH().getMsh6_ReceivingFacility().getHd1_NamespaceID().setValue(receiveSystemCode);
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
        String nowDate = df.format(new Date());
        ack.getMSH().getMsh7_DateTimeOfMessage().getTs1_TimeOfAnEvent().setValue(nowDate);
        ack.getMSA().getMsa1_AcknowledgementCode().setValue(messageStatus);
        ack.getMSA().getMsa2_MessageControlID().setValue(guid);
        ack.getMSH().getMsh9_MessageType().getMsg1_MessageType().setValue(messageType);
        ack.getMSH().getMsh9_MessageType().getMsg2_TriggerEvent().setValue(triggerEvent);
        ack.getMSH().getMsh10_MessageControlID().setValue(getUuid());
        ack.getMSH().getMsh11_ProcessingID().getPt1_ProcessingID().setValue("P");
        ack.getMSH().getMsh12_VersionID().getVid1_VersionID().setValue(versionId);
        ack.getMSH().getMsh20_AlternateCharacterSetHandlingScheme().setValue(hospitalName);
        return ack.toString();
    }

    public String getUuid() {
        String uuid = null;
        for (int i = 0; i < 10; i++) {
            uuid = UUID.randomUUID().toString().replaceAll("-", "");
        }
        return uuid;
    }

    public int stringToInteger(String string) {
        if (string != null) {
            return Integer.parseInt(string);
        }
        return 0;
    }

    public String getrealVal(String val, String operationSch) {
        String realVal = null;
        if (val == null || val.equals("")) {
            realVal = operationSch;
        } else {
            realVal = val;
        }
        return realVal;
    }
}
